<template><div><p>本文档最新版为 <a href="https://learnku.com/docs/laravel/10.x" target="_blank" rel="noopener noreferrer">10.x</a>，旧版本可能放弃维护，推荐阅读最新版！</p>
<h2 id="laravel-测试之-浏览器测试-laravel-dusk" tabindex="-1"><a class="header-anchor" href="#laravel-测试之-浏览器测试-laravel-dusk"><span>Laravel 测试之 - 浏览器测试 (Laravel Dusk)</span></a></h2>
<ul>
<li><a href="#introduction">简介</a></li>
<li><a href="#installation">安装</a>
<ul>
<li><a href="#using-other-browsers">使用其他浏览器</a></li>
</ul>
</li>
<li><a href="#getting-started">开始</a>
<ul>
<li><a href="#generating-tests">创建测试</a></li>
<li><a href="#running-tests">运行测试</a></li>
<li><a href="#environment-handling">环境处理</a></li>
<li><a href="#creating-browsers">创建浏览器</a></li>
<li><a href="#authentication">认证</a></li>
</ul>
</li>
<li><a href="#interacting-with-elements">与元素交互</a>
<ul>
<li><a href="#clicking-links">点击链接</a></li>
<li><a href="#text-values-and-attributes">文本、值和属性</a></li>
<li><a href="#using-forms">使用表单</a></li>
<li><a href="#attaching-files">附加文件</a></li>
<li><a href="#using-the-keyboard">使用键盘</a></li>
<li><a href="#using-the-mouse">使用鼠标</a></li>
<li><a href="#scoping-selectors">元素作用域</a></li>
<li><a href="#waiting-for-elements">等待元素</a></li>
</ul>
</li>
<li><a href="#available-assertions">可用的断言</a></li>
<li><a href="#pages">页面</a>
<ul>
<li><a href="#generating-pages">创建页面</a></li>
<li><a href="#configuring-pages">配置页面</a></li>
<li><a href="#navigating-to-pages">导航至页面</a></li>
<li><a href="#shorthand-selectors">选择器简写</a></li>
<li><a href="#page-methods">页面方法</a></li>
</ul>
</li>
<li><a href="#continuous-integration">持续集成</a>
<ul>
<li><a href="#running-tests-on-travis-ci">Travis CI</a></li>
<li><a href="#running-tests-on-circle-ci">CircleCI</a></li>
</ul>
</li>
</ul>
<h2 id="简介" tabindex="-1"><a class="header-anchor" href="#简介"><span>简介</span></a></h2>
<p>Laravel Dusk 提供了富有表现力、简单易用的浏览器自动化以及相应的测试 API。Dusk 只需要使用一个单独的 <a href="https://sites.google.com/a/chromium.org/chromedriver/home" target="_blank" rel="noopener noreferrer">ChromeDriver</a>，不再需要在你的机器中安装 JDK 或者 Selenium。不过，依然可以按照你自己的需要安装其他 Selenium 兼容的驱动引擎。</p>
<h2 id="安装" tabindex="-1"><a class="header-anchor" href="#安装"><span>安装</span></a></h2>
<p>将 <code v-pre>laravel/dusk</code> 添加到你的项目 Composer 依赖中：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">composer <span class="token keyword">require</span> <span class="token operator">--</span>dev laravel<span class="token operator">/</span>dusk<span class="token punctuation">:</span><span class="token string double-quoted-string">"^2.0"</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><blockquote>
<p>{note} 永远不要在生产环境安装 Dusk。否则，任何人都可以未经授权地访问你的应用。</p>
</blockquote>
<p>安装了 Dusk 之后，你需要注册 <code v-pre>Laravel\Dusk\DuskServiceProvider</code> 服务提供者。通常，这将通过 Laravel 的服务提供者自动发现机制去自动完成。</p>
<p>接下来运行 <code v-pre>dusk:install</code> Artisan 命令：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">php artisan dusk<span class="token punctuation">:</span>install</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>这将会在你的 <code v-pre>tests</code> 目录下创建一个 <code v-pre>Browser</code> 目录，同时包含了一个测试用例模版。然后在你的 <code v-pre>.env</code> 文件中设置 <code v-pre>APP_URL</code> 环境变量。这个变量值要与你在浏览器访问你应用的 URL 一致。</p>
<p>使用 <code v-pre>dusk</code> Artisan 命令来运行你的测试。<code v-pre>dusk</code> 命令可以接受任何 <code v-pre>phpunit</code> 能接受的参数：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">php artisan dusk</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="使用其他浏览器" tabindex="-1"><a class="header-anchor" href="#使用其他浏览器"><span>使用其他浏览器</span></a></h3>
<p>Dusk 默认使用 Google Chrome 和 <a href="https://sites.google.com/a/chromium.org/chromedriver/home" target="_blank" rel="noopener noreferrer">ChromeDriver</a> 来运行你的浏览器测试。当然，你也可以运行你的 Selenium 服务器，然后对任何你想要的浏览器运行测试。</p>
<p>打开你的 <code v-pre>tests/DuskTestCase.php</code> 文件，这个文件是你应用中最基础的 Dusk 测试用例。你可以在这个文件中移除 <code v-pre>startChromeDriver</code> 方法。这样 Dusk 就不会自动运行 ChromeDriver：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 为 Dusk 的测试做准备。</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@beforeClass</span></span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">void</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">function</span> <span class="token function-definition function">prepare</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// static::startChromeDriver();</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然后，你可以通过简单地修改 <code v-pre>driver</code> 方法来连接到你指定的 URL 和端口。同时，你要修改传递给 WebDriver 的「desired capabilities」：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 创建 RemoteWebDriver 实例。</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token punctuation">\</span>Facebook<span class="token punctuation">\</span>WebDriver<span class="token punctuation">\</span>Remote<span class="token punctuation">\</span>RemoteWebDriver</span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">protected</span> <span class="token keyword">function</span> <span class="token function-definition function">driver</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token class-name static-context">RemoteWebDriver</span><span class="token operator">::</span><span class="token function">create</span><span class="token punctuation">(</span></span>
<span class="line">        <span class="token string single-quoted-string">'http://localhost:4444/wd/hub'</span><span class="token punctuation">,</span> <span class="token class-name static-context">DesiredCapabilities</span><span class="token operator">::</span><span class="token function">phantomjs</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="开始" tabindex="-1"><a class="header-anchor" href="#开始"><span>开始</span></a></h2>
<h3 id="创建测试" tabindex="-1"><a class="header-anchor" href="#创建测试"><span>创建测试</span></a></h3>
<p>使用 <code v-pre>dusk:make</code> Artisan 命令来创建 Dusk 测试。创建好的测试类会放在 <code v-pre>tests/Browser</code> 目录：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">php artisan dusk<span class="token punctuation">:</span>make LoginTest</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="运行测试" tabindex="-1"><a class="header-anchor" href="#运行测试"><span>运行测试</span></a></h3>
<p>使用 <code v-pre>dusk</code> Artisan 命令来运行你的浏览器测试：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">php artisan dusk</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><code v-pre>dusk</code> 命令可以接受任何 PHPUnit 能接受的参数。例如，让你可以只在指定 <a href="https://phpunit.de/manual/current/en/appendixes.annotations.html#appendixes.annotations.group" target="_blank" rel="noopener noreferrer">分组</a> 中运行测试:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">php artisan dusk <span class="token operator">--</span>group<span class="token operator">=</span>foo</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="手动运行-chromedriver" tabindex="-1"><a class="header-anchor" href="#手动运行-chromedriver"><span>手动运行 ChromeDriver</span></a></h4>
<p>Dusk 默认会尝试自动运行 ChromeDriver。如果在你特定的系统中不能正常运行，你可以在运行 <code v-pre>dusk</code> 命令之前通过手动的方式来运行 ChromeDriver。如果你选择手动运行 ChromeDriver，你需要在你的 <code v-pre>tests/DuskTestCase.php</code> 文件中注释掉下面这行：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 为 Dusk 的测试做准备。</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@beforeClass</span></span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">void</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">function</span> <span class="token function-definition function">prepare</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// static::startChromeDriver();</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>另外，如果你是在非 9515 端口运行 ChromeDriver，你需要在 <code v-pre>tests/DuskTestCase.php</code> 修改 <code v-pre>driver</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 创建 RemoteWebDriver 实例。</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token punctuation">\</span>Facebook<span class="token punctuation">\</span>WebDriver<span class="token punctuation">\</span>Remote<span class="token punctuation">\</span>RemoteWebDriver</span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">protected</span> <span class="token keyword">function</span> <span class="token function-definition function">driver</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token class-name static-context">RemoteWebDriver</span><span class="token operator">::</span><span class="token function">create</span><span class="token punctuation">(</span></span>
<span class="line">        <span class="token string single-quoted-string">'http://localhost:9515'</span><span class="token punctuation">,</span> <span class="token class-name static-context">DesiredCapabilities</span><span class="token operator">::</span><span class="token function">chrome</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="环境处理" tabindex="-1"><a class="header-anchor" href="#环境处理"><span>环境处理</span></a></h3>
<p>在你项目的根目录创建 <code v-pre>.env.dusk.{environment}</code> 文件来强制 Dusk 使用自己的的环境文件来运行测试。简单来说，如果你想要以 <code v-pre>local</code> 环境来运行 <code v-pre>dusk</code> 命令，你需要创建一个 <code v-pre>.env.dusk.local</code> 文件。</p>
<p>运行测试的时候，Dusk 会备份你的 <code v-pre>.env</code> 文件，然后重命名你的 Dusk 环境文件为 <code v-pre>.env</code>。一旦测试结束之后，将会恢复你的 <code v-pre>.env</code> 文件。</p>
<h3 id="创建浏览器" tabindex="-1"><a class="header-anchor" href="#创建浏览器"><span>创建浏览器</span></a></h3>
<p>让我们来写一个测试用例，这个测试用例可以验证我们是否能够登录系统。生成测试类之后，我们修改这个类，让它可以跳转到登录页面，输入某些登录信息，点击「登录」按钮。使用 <code v-pre>browse</code> 方法来创建一个浏览器实例：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">Tests<span class="token punctuation">\</span>Browser</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Tests<span class="token punctuation">\</span>DuskTestCase</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Dusk<span class="token punctuation">\</span>Chrome</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Foundation<span class="token punctuation">\</span>Testing<span class="token punctuation">\</span>DatabaseMigrations</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">ExampleTest</span> <span class="token keyword">extends</span> <span class="token class-name">DuskTestCase</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">DatabaseMigrations</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 一个基本的浏览器测试示例。</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">void</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">testBasicExample</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$user</span> <span class="token operator">=</span> <span class="token function">factory</span><span class="token punctuation">(</span><span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'email'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'taylor@laravel.com'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">browse</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$browser</span><span class="token punctuation">)</span> <span class="token keyword">use</span> <span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">visit</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/login'</span><span class="token punctuation">)</span></span>
<span class="line">                    <span class="token operator">-></span><span class="token function">type</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'email'</span><span class="token punctuation">,</span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token property">email</span><span class="token punctuation">)</span></span>
<span class="line">                    <span class="token operator">-></span><span class="token function">type</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'password'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'secret'</span><span class="token punctuation">)</span></span>
<span class="line">                    <span class="token operator">-></span><span class="token function">press</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Login'</span><span class="token punctuation">)</span></span>
<span class="line">                    <span class="token operator">-></span><span class="token function">assertPathIs</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/home'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在上面的示例中，你可以看到 <code v-pre>browse</code> 方法接受一个回调参数。 Dusk 会自动将这个浏览器实例注入到回调当中，而这个浏览器实例可以让你与你的应用之间进行交互和断言。</p>
<blockquote>
<p>{tip} 这个测试用例可以测试由 <code v-pre>make:auth</code> Artisan 命令来生成的登录页面。</p>
</blockquote>
<h4 id="创建多个浏览器" tabindex="-1"><a class="header-anchor" href="#创建多个浏览器"><span>创建多个浏览器</span></a></h4>
<p>有时你可能需要多个浏览器才能正确地进行测试。例如，你可能需要使用多个浏览器测试通过 websockets 通讯的在线聊天页面。要想创建多个浏览器，你只需要简单地在 <code v-pre>browse</code> 方法的回调中，用名字来区分浏览器实例，然后传给回调来 「申请」 多个浏览器实例即可：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token function">browse</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$first</span><span class="token punctuation">,</span> <span class="token variable">$second</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$first</span><span class="token operator">-></span><span class="token function">loginAs</span><span class="token punctuation">(</span><span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line">          <span class="token operator">-></span><span class="token function">visit</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/home'</span><span class="token punctuation">)</span></span>
<span class="line">          <span class="token operator">-></span><span class="token function">waitForText</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Message'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$second</span><span class="token operator">-></span><span class="token function">loginAs</span><span class="token punctuation">(</span><span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line">           <span class="token operator">-></span><span class="token function">visit</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/home'</span><span class="token punctuation">)</span></span>
<span class="line">           <span class="token operator">-></span><span class="token function">waitForText</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Message'</span><span class="token punctuation">)</span></span>
<span class="line">           <span class="token operator">-></span><span class="token function">type</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'message'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'Hey Taylor'</span><span class="token punctuation">)</span></span>
<span class="line">           <span class="token operator">-></span><span class="token function">press</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Send'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$first</span><span class="token operator">-></span><span class="token function">waitForText</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Hey Taylor'</span><span class="token punctuation">)</span></span>
<span class="line">          <span class="token operator">-></span><span class="token function">assertSee</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Jeffrey Way'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="认证" tabindex="-1"><a class="header-anchor" href="#认证"><span>认证</span></a></h3>
<p>你可能经常会测试一些需要认证的页面。你可以使用 Dusk 的 <code v-pre>loginAs</code> 方法来避免每个测试都去登录页面登录一次。<code v-pre>loginAs</code> 方法可以使用用户 ID 或者用户模型实例：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token function">browse</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$first</span><span class="token punctuation">,</span> <span class="token variable">$second</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$first</span><span class="token operator">-></span><span class="token function">loginAs</span><span class="token punctuation">(</span><span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line">          <span class="token operator">-></span><span class="token function">visit</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/home'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p>{note} 使用 <code v-pre>loginAs</code> 方法后, 该用户的 session 将会持久化供其他测试用例使用。</p>
</blockquote>
<h2 id="与元素交互" tabindex="-1"><a class="header-anchor" href="#与元素交互"><span>与元素交互</span></a></h2>
<h3 id="点击链接" tabindex="-1"><a class="header-anchor" href="#点击链接"><span>点击链接</span></a></h3>
<p>你可以在你的浏览器实例中使用 <code v-pre>clickLink</code> 方法来模拟点击一个链接。<code v-pre>clickLink</code> 方法会点击传入的显示文本：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">clickLink</span><span class="token punctuation">(</span><span class="token variable">$linkText</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><blockquote>
<p>{note} 这方法基于 JQuery 来进行交互。如果页面中没有可用的 jQuery，Dusk 会自动将 jQuery 注入到页面中。所以他可能会增加测试的时间。</p>
</blockquote>
<h3 id="文本、值和属性" tabindex="-1"><a class="header-anchor" href="#文本、值和属性"><span>文本、值和属性</span></a></h3>
<h4 id="获取和设置值" tabindex="-1"><a class="header-anchor" href="#获取和设置值"><span>获取和设置值</span></a></h4>
<p>Dusk 提供了几种方法让你和当前页面元素中的显示文本、值和属性进行交互。例如，想获得某个指定选择器对应元素的「值」，你可以使用 <code v-pre>value</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token comment">// 获取值...</span></span>
<span class="line"><span class="token variable">$value</span> <span class="token operator">=</span> <span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">value</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'selector'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 设置值...</span></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">value</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'selector'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'value'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="获取文本" tabindex="-1"><a class="header-anchor" href="#获取文本"><span>获取文本</span></a></h4>
<p><code v-pre>text</code> 方法用来获取匹配指定选择器的元素的显示文本：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$text</span> <span class="token operator">=</span> <span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">text</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'selector'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="获取属性" tabindex="-1"><a class="header-anchor" href="#获取属性"><span>获取属性</span></a></h4>
<p><code v-pre>attribute</code> 方法用来获取匹配指定选择器的元素的属性：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$attribute</span> <span class="token operator">=</span> <span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">attribute</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'selector'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'value'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="使用表单" tabindex="-1"><a class="header-anchor" href="#使用表单"><span>使用表单</span></a></h3>
<h4 id="输入值" tabindex="-1"><a class="header-anchor" href="#输入值"><span>输入值</span></a></h4>
<p>Dusk 提供了与表单和 input 元素交互的各种方法。首先，让我们来看看一个在 input 框中输入文本的示例：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">type</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'email'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'taylor@laravel.com'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>注意：虽然 <code v-pre>type</code> 方法可以传递 CSS 选择器作为第一个参数，但这并不是强制要求。如果传入的不是 CSS 选择器，Dusk 会尝试匹配传入值与 <code v-pre>name</code> 属性相符的 input 框，如果没找到，最后 Dusk 会尝试查找匹配传入值与 <code v-pre>name</code> 属性相符的 <code v-pre>textarea</code>。</p>
<p>你可以使用 <code v-pre>clear</code> 方法来 「清除」 输入值。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">clear</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'email'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="下拉菜单" tabindex="-1"><a class="header-anchor" href="#下拉菜单"><span>下拉菜单</span></a></h4>
<p>你可以使用 <code v-pre>select</code> 方法来选择下来菜单中的某个选项。类似于 <code v-pre>type</code> 方法，<code v-pre>select</code> 方法并不是一定要传入 CSS 选择器。当你使用 <code v-pre>select</code> 方法的时候应该注意，你传的值应该是选项实际的值，而不是显示的值：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">select</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'size'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'Large'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>你也可以通过省略第二个参数来随机选择一个选项：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">select</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'size'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="复选框" tabindex="-1"><a class="header-anchor" href="#复选框"><span>复选框</span></a></h4>
<p>你可以使用 <code v-pre>check</code> 方法来选中某个复选框。像其他 input 相关的方法一样，并不是必须传入 CSS 选择器。如果准确的选择器没法找到的时候，Dusk 会搜索与 <code v-pre>name</code> 属性匹配的复选框：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">check</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'terms'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">uncheck</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'terms'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="单选按钮" tabindex="-1"><a class="header-anchor" href="#单选按钮"><span>单选按钮</span></a></h4>
<p>你可以使用 <code v-pre>radio</code> 方法来选择某个单选选项。同样的，并不是必须传入 CSS 选择器。如果准确的选择器没法找到的时候，Dusk 会搜索与 <code v-pre>name</code> 属性或者 <code v-pre>value</code> 属性匹配的单选按钮：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">radio</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'version'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'php7'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="附加文件" tabindex="-1"><a class="header-anchor" href="#附加文件"><span>附加文件</span></a></h3>
<p><code v-pre>attach</code> 方法可以用来附加一个文件到 <code v-pre>file</code> input 框中。同样的，并不是必须传入 CSS 选择器。如果准确的选择器没法找到的时候，Dusk 会搜索与 <code v-pre>name</code> 属性匹配的文件输入框：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">attach</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'photo'</span><span class="token punctuation">,</span> <span class="token constant">__DIR__</span><span class="token operator">.</span><span class="token string single-quoted-string">'/photos/me.png'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="使用键盘" tabindex="-1"><a class="header-anchor" href="#使用键盘"><span>使用键盘</span></a></h3>
<p><code v-pre>keys</code> 方法让你可以在指定元素中输入比 <code v-pre>type</code> 方法更加复杂的输入序列。例如，你可以在输入值的同时按下按键。在本例中，在输入 <code v-pre>taylor</code> 时，<code v-pre>shift</code> 按键也同时被按下，当 <code v-pre>taylor</code> 输入完之后，<code v-pre>otwell</code> 则会正常输入，不会按下任何按键：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">keys</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'selector'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'{shift}'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'taylor'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'otwell'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>甚至你可以在你应用中选中某个元素之后按下 「快捷键」：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">keys</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.app'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'{command}'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'j'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><blockquote>
<p>{tip} 所有包在 <code v-pre>{}</code> 中的修饰按键，都应该与 <code v-pre>Facebook\WebDriver\WebDriverKeys</code> 类中定义的常量一致。你可以在 <a href="https://github.com/facebook/php-webdriver/blob/community/lib/WebDriverKeys.php" target="_blank" rel="noopener noreferrer">GitHub 中找到这个类</a>。</p>
</blockquote>
<h3 id="使用鼠标" tabindex="-1"><a class="header-anchor" href="#使用鼠标"><span>使用鼠标</span></a></h3>
<h4 id="点击元素" tabindex="-1"><a class="header-anchor" href="#点击元素"><span>点击元素</span></a></h4>
<p><code v-pre>click</code> 方法用来「点击」与指定选择器匹配的元素：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">click</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.selector'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="mouseover" tabindex="-1"><a class="header-anchor" href="#mouseover"><span>Mouseover</span></a></h4>
<p><code v-pre>mouseover</code> 方法用来将鼠标悬停在与指定选择器匹配的元素：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">mouseover</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.selector'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="拖拽" tabindex="-1"><a class="header-anchor" href="#拖拽"><span>拖拽</span></a></h4>
<p><code v-pre>drag</code> 方法用来拖拽与指定选择器匹配的元素到另外一个元素那里：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">drag</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.from-selector'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'.to-selector'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>或者将元素向一个方向拖拽</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">dragLeft</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.selector'</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">dragRight</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.selector'</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">dragUp</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.selector'</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">dragDown</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.selector'</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="元素作用域" tabindex="-1"><a class="header-anchor" href="#元素作用域"><span>元素作用域</span></a></h3>
<p>有时候你可能希望在某个与选择器匹配的元素中执行一系列的操作。例如，你可能希望在某个 table 中断言有某些文本，然后在同一个 table 中点击按钮。你可以使用 <code v-pre>with</code> 方法来达到这个目的。<code v-pre>with</code> 方法的回调参数中，所有的操作都作用在同一个原始选择器上:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">with</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.table'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$table</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$table</span><span class="token operator">-></span><span class="token function">assertSee</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Hello World'</span><span class="token punctuation">)</span></span>
<span class="line">          <span class="token operator">-></span><span class="token function">clickLink</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Delete'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="等待元素" tabindex="-1"><a class="header-anchor" href="#等待元素"><span>等待元素</span></a></h3>
<p>在测试应用的时候，由于经常会用到 JavaScript。所以经常需要在开始之前「等待」某些元素或者数据，以确保在测试中是有效可用的。Dusk 让这变得简单。使用一系列的方法，让你可以等待页面元素完全显示，甚至是指定的 JavaScript 表达式返回 <code v-pre>true</code> 的时候才继续执行测试：</p>
<h4 id="等待" tabindex="-1"><a class="header-anchor" href="#等待"><span>等待</span></a></h4>
<p>如果你需要暂停指定毫秒数，你可以使用 <code v-pre>pause</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">pause</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="等待选择器元素" tabindex="-1"><a class="header-anchor" href="#等待选择器元素"><span>等待选择器元素</span></a></h4>
<p><code v-pre>waitFor</code> 方法用来暂停测试的执行，直到与 CSS 选择器匹配的元素显示在页面中。在抛出异常之前，默认最多暂停 5 秒。如果需要，你也可以自定义超时时间作为第二个参数传给这个方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token comment">// 最多为这个元素的显示等待 5 秒...</span></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">waitFor</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.selector'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 最多为这个元素的显示等待 1 秒...</span></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">waitFor</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.selector'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>你也可以等待指定元素直到超时都还在页面中找不到：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">waitUntilMissing</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.selector'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">waitUntilMissing</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.selector'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="可用元素的作用域" tabindex="-1"><a class="header-anchor" href="#可用元素的作用域"><span>可用元素的作用域</span></a></h4>
<p>有时候，你可能想要等待与指定选择器匹配的元素，然后与这元素进行交互。例如，你可能需要等待某个模态窗口可用，然后在模态窗口中点击「OK」按钮。在这种情况下，可以使用 <code v-pre>whenAvailable</code> 方法。所有闭包中的操作都针对这个原始的元素：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">whenAvailable</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.modal'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$modal</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$modal</span><span class="token operator">-></span><span class="token function">assertSee</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Hello World'</span><span class="token punctuation">)</span></span>
<span class="line">          <span class="token operator">-></span><span class="token function">press</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'OK'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="等待文本" tabindex="-1"><a class="header-anchor" href="#等待文本"><span>等待文本</span></a></h4>
<p><code v-pre>waitForText</code> 方法用于等待指定文本，直到显示在页面中为止：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token comment">// 最多为这个文本的显示等待 5 秒...</span></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">waitForText</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Hello World'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 最多为这个文本的显示等待 1 秒...</span></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">waitForText</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Hello World'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="等待超链接" tabindex="-1"><a class="header-anchor" href="#等待超链接"><span>等待超链接</span></a></h4>
<p><code v-pre>waitForLink</code> 方法用来等待指定链接文本，直到链接文本显示在页面中为止：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token comment">// 最多为这个链接的显示等待 5 秒...</span></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">waitForLink</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Create'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 最多为这个链接的显示等待 1 秒...</span></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">waitForLink</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Create'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="等待页面跳转" tabindex="-1"><a class="header-anchor" href="#等待页面跳转"><span>等待页面跳转</span></a></h4>
<p>在进行例如 <code v-pre>$browser-&gt;assertPathIs('/home')</code>的路径断言时，如果 <code v-pre>window.location.pathname</code> 为异步完成，断言就会失败。你需要使用 <code v-pre>waitForLocation</code> 方法去等待指定的跳转：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">waitForLocation</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/secret'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="等待页面重载" tabindex="-1"><a class="header-anchor" href="#等待页面重载"><span>等待页面重载</span></a></h4>
<p>如果你需要在页面重载后进行断言，你可以使用 <code v-pre>waitForReload</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">click</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.some-action'</span><span class="token punctuation">)</span></span>
<span class="line">        <span class="token operator">-></span><span class="token function">waitForReload</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">        <span class="token operator">-></span><span class="token function">assertSee</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'something'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="等待-javascript-表达式" tabindex="-1"><a class="header-anchor" href="#等待-javascript-表达式"><span>等待 JavaScript 表达式</span></a></h4>
<p>有时候你可能想要暂停测试用例的执行，直到指定的 JavaScript 表达式计算结果为 <code v-pre>true</code>。使用 <code v-pre>waitUntil</code> 方法可以让你很容易做到这一点。传递表达式给方法的时候，你不需要包括 <code v-pre>return</code> 关键词或者结束分号：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token comment">// 最多为表达式的成立等待 5 秒...</span></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">waitUntil</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'App.dataLoaded'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">waitUntil</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'App.data.servers.length > 0'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 最多为表达式的成立等待 1 秒...</span></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">waitUntil</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'App.data.servers.length > 0'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="等待回调" tabindex="-1"><a class="header-anchor" href="#等待回调"><span>等待回调</span></a></h4>
<p>Dusk 中的许多「等待」方法依赖于 <code v-pre>waitUsing</code> 方法。该方法可以等待一个回调返回 <code v-pre>true</code>。<code v-pre>waitUsing</code> 接受的参数为最大等待秒数、闭包的执行间隔、闭包以及一个可选的错误信息。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">waitUsing</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">use</span> <span class="token punctuation">(</span><span class="token variable">$something</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$something</span><span class="token operator">-></span><span class="token function">isReady</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string double-quoted-string">"Something wasn't ready in time."</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="可用的断言" tabindex="-1"><a class="header-anchor" href="#可用的断言"><span>可用的断言</span></a></h2>
<p>Dusk 为你的应用提供了一系列的断言方法。所有的断言方法都记录在下面的表格中：</p>
<table>
<thead>
<tr>
<th>Assertion</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code v-pre>$browser-&gt;assertTitle($title)</code></td>
<td>断言页面标题符合指定文本。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertTitleContains($title)</code></td>
<td>断言页面标题包含指定文本。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertPathBeginsWith($path)</code></td>
<td>断言当前 URL 开始于指定的值。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertPathIs('/home')</code></td>
<td>断言当前 URL 为指定的值。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertPathIsNot('/home')</code></td>
<td>断言当前 URL 不是指定的值。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertRouteIs($name, $parameters)</code></td>
<td>断言当前 URL 为指定的路由生成。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertQueryStringHas($name, $value)</code></td>
<td>断言指定的查询条件为指定的值。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertQueryStringMissing($name)</code></td>
<td>断言不存在指定的查询条件。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertHasQueryStringParameter($name)</code></td>
<td>断言存在指定的查询条件。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertHasCookie($name)</code></td>
<td>断言存在指定 Cookie。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertCookieValue($name, $value)</code></td>
<td>断言指定 Cookie 为指定值。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertPlainCookieValue($name, $value)</code></td>
<td>断言一个未加密的 Cookie 为指定值。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertSee($text)</code></td>
<td>断言页面中存在指定文本。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertDontSee($text)</code></td>
<td>断言页面中不存在指定文本。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertSeeIn($selector, $text)</code></td>
<td>断言匹配指定选择器中存在指定文本。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertDontSeeIn($selector, $text)</code></td>
<td>断言匹配指定选择器中不存在指定文本。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertSourceHas($code)</code></td>
<td>断言页面的源码中存在指定的值。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertSourceMissing($code)</code></td>
<td>断言页面的源码中不存在指定的值。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertSeeLink($linkText)</code></td>
<td>断言页面中存在指定链接。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertDontSeeLink($linkText)</code></td>
<td>断言页面中不存在指定链接。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertInputValue($field, $value)</code></td>
<td>断言指定的 input 输入框为指定的值。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertInputValueIsNot($field, $value)</code></td>
<td>断言指定的 input 输入框不为指定的值。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertChecked($field)</code></td>
<td>断言指定的复选框已被选中。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertNotChecked($field)</code></td>
<td>断言指定的复选框未被选中。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertRadioSelected($field, $value)</code></td>
<td>断言指定的单选框已被选中。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertRadioNotSelected($field, $value)</code></td>
<td>断言指定的单选框未被选中。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertSelected($field, $value)</code></td>
<td>断言指定的下拉列表指定的值被选中。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertNotSelected($field, $value)</code></td>
<td>断言指定的下拉列表指定的值未被选中</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertSelectHasOptions($field, $values)</code></td>
<td>断言指定数组中的值存在于指定的下拉列表的选项中。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertSelectMissingOptions($field, $values)</code></td>
<td>断言指定数组中的值不存在于指定的下拉列表的选项中。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertSelectHasOption($field, $value)</code></td>
<td>断言指定的值存在于指定的下拉列表的选项中。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertValue($selector, $value)</code></td>
<td>断言匹配指定选择器的元素为指定值。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertVisible($selector)</code></td>
<td>断言匹配指定选择器的元素是可见的。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertMissing($selector)</code></td>
<td>断言匹配指定选择器的元素是不可见的。</td>
</tr>
<tr>
<td><code v-pre>$browser-&gt;assertDialogOpened($message)</code></td>
<td>断言消息为指定值的对话框已被打开。</td>
</tr>
</tbody>
</table>
<h2 id="pages" tabindex="-1"><a class="header-anchor" href="#pages"><span>Pages</span></a></h2>
<p>有时候，测试有一些复杂的动作需要顺序执行。 这很容易让你的测试代码变得难读，并且难以理解。页面允许你定义语义化的动作行为，然后你可以在指定页面中使用单个方法。页面也允许你为你的应用或者单个页面定义简写的公共选择器。</p>
<h3 id="创建页面" tabindex="-1"><a class="header-anchor" href="#创建页面"><span>创建页面</span></a></h3>
<p>使用 <code v-pre>dusk:page</code> Artisan 命令来创建页面对象。所有的页面对象会存放在 <code v-pre>tests/Browser/Pages</code> 目录中：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">php artisan dusk<span class="token punctuation">:</span>page Login</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="配置页面" tabindex="-1"><a class="header-anchor" href="#配置页面"><span>配置页面</span></a></h3>
<p>页面默认拥有 3 个方法： <code v-pre>url</code>， <code v-pre>assert</code> 和 <code v-pre>elements</code>。 在这里我们先详述 <code v-pre>url</code> 和 <code v-pre>assert</code> 方法。<code v-pre>elements</code> 方法将会 <a href="#shorthand-selectors">在下面详细描述</a>。</p>
<h4 id="url-方法" tabindex="-1"><a class="header-anchor" href="#url-方法"><span><code v-pre>url</code> 方法</span></a></h4>
<p><code v-pre>url</code> 方法应该返回表示页面 URL 的路径。 Dusk 将会在浏览器中使用这个 URL 来导航到具体页面：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * Get the URL for the page.</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">string</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">url</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token string single-quoted-string">'/login'</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="the-assert-method" tabindex="-1"><a class="header-anchor" href="#the-assert-method"><span>The <code v-pre>assert</code> Method</span></a></h4>
<p><code v-pre>assert</code> 方法可以作出任何断言来验证浏览器是否在指定页面上。这个方法并不是必须的。你可以根据你自己的需求来做出这些断言。这些断言会在你浏览到这个页面的时候自动执行：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 断言浏览器是否正在指定页面。</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">void</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">assert</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Browser</span> <span class="token variable">$browser</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">assertPathIs</span><span class="token punctuation">(</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token function">url</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="导航至页面" tabindex="-1"><a class="header-anchor" href="#导航至页面"><span>导航至页面</span></a></h3>
<p>一旦页面配置好之后，你可以使用 <code v-pre>visit</code> 方法导航至页面：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Tests<span class="token punctuation">\</span>Browser<span class="token punctuation">\</span>Pages<span class="token punctuation">\</span>Login</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">visit</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Login</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>有时候，你可能已经在指定页面了，你需要的只是「加载」当前页面的选择器和方法到当前测试中来。常见的例子有：当你按下一个按钮的时候，你会被重定向至指定页面，而不是直接导航至指定页面。在这种情况下，你需要使用 <code v-pre>on</code> 方法来加载页面：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Tests<span class="token punctuation">\</span>Browser<span class="token punctuation">\</span>Pages<span class="token punctuation">\</span>CreatePlaylist</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">visit</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/dashboard'</span><span class="token punctuation">)</span></span>
<span class="line">        <span class="token operator">-></span><span class="token function">clickLink</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Create Playlist'</span><span class="token punctuation">)</span></span>
<span class="line">        <span class="token operator">-></span><span class="token function">on</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">CreatePlaylist</span><span class="token punctuation">)</span></span>
<span class="line">        <span class="token operator">-></span><span class="token function">assertSee</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'@create'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="选择器简写" tabindex="-1"><a class="header-anchor" href="#选择器简写"><span>选择器简写</span></a></h3>
<p><code v-pre>elements</code> 方法允许你为页面中的任何 CSS 选择器定义简单易记的简写。例如，让我们为应用登录页中的 <code v-pre>email</code> 输入框定义一个简写：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 获取页面的元素简写。</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">array</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">elements</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'@email'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'input[name=email]'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>现在你可以用这个简写来代替之前在页面中使用的完整 CSS 选择器：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">type</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'@email'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'taylor@laravel.com'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="全局的选择器简写" tabindex="-1"><a class="header-anchor" href="#全局的选择器简写"><span>全局的选择器简写</span></a></h4>
<p>安装 Dusk 之后，<code v-pre>Page</code> 基类存放在你的 <code v-pre>tests/Browser/Pages</code> 目录。该类中包含一个 <code v-pre>siteElements</code> 方法，这个方法可以用来定义全局的选择器简写，这样在你应用中每个页面都可以使用这些全局选择器简写了：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 获取站点全局的选择器简写。</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">array</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">function</span> <span class="token function-definition function">siteElements</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'@element'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'#selector'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="页面方法" tabindex="-1"><a class="header-anchor" href="#页面方法"><span>页面方法</span></a></h3>
<p>处理页面中已经定义的默认方法之外，你还可以定义在整个测试过程中会使用到的其他方法。例如，让我们假设一下我们正在开发一个音乐管理应用，在应用中都可能需要一个公共的方法来创建列表，而不是在每一页、每一个测试类中都重写一遍创建播放列表的逻辑，这时候你可以在你的页面类中定义一个 <code v-pre>createPlaylist</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">Tests<span class="token punctuation">\</span>Browser<span class="token punctuation">\</span>Pages</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Dusk<span class="token punctuation">\</span>Browser</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Dashboard</span> <span class="token keyword">extends</span> <span class="token class-name">Page</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 其他页面方法...</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 创建一个新的播放列表。</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@param</span>  <span class="token class-name"><span class="token punctuation">\</span>Laravel<span class="token punctuation">\</span>Dusk<span class="token punctuation">\</span>Browser</span>  <span class="token parameter">$browser</span></span>
<span class="line">     * <span class="token keyword">@param</span>  <span class="token class-name"><span class="token keyword">string</span></span>  <span class="token parameter">$name</span></span>
<span class="line">     * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">void</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">createPlaylist</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Browser</span> <span class="token variable">$browser</span><span class="token punctuation">,</span> <span class="token variable">$name</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">type</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'name'</span><span class="token punctuation">,</span> <span class="token variable">$name</span><span class="token punctuation">)</span></span>
<span class="line">                <span class="token operator">-></span><span class="token function">check</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'share'</span><span class="token punctuation">)</span></span>
<span class="line">                <span class="token operator">-></span><span class="token function">press</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Create Playlist'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>方法被定义之后，你可以在任何使用到该页的测试中使用这个方法了。浏览器实例会自动传递该页面方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Tests<span class="token punctuation">\</span>Browser<span class="token punctuation">\</span>Pages<span class="token punctuation">\</span>Dashboard</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$browser</span><span class="token operator">-></span><span class="token function">visit</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Dashboard</span><span class="token punctuation">)</span></span>
<span class="line">        <span class="token operator">-></span><span class="token function">createPlaylist</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'My Playlist'</span><span class="token punctuation">)</span></span>
<span class="line">        <span class="token operator">-></span><span class="token function">assertSee</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'My Playlist'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="持续集成" tabindex="-1"><a class="header-anchor" href="#持续集成"><span>持续集成</span></a></h2>
<h3 id="travis-ci" tabindex="-1"><a class="header-anchor" href="#travis-ci"><span>Travis CI</span></a></h3>
<p>在 Travis CI 中运行 Dusk 时需要「sudo-enabled」的 Ubuntu 14.04 (Trusty) 环境。由于 Travis CI 不是图形环境，我们需要一些额外的步骤去启动 Chrome 浏览器，另外，我们需要使用 <code v-pre>php artisan serve</code> 命令去启动 PHP 的内置服务器。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">sudo<span class="token punctuation">:</span> required</span>
<span class="line">dist<span class="token punctuation">:</span> trusty</span>
<span class="line"></span>
<span class="line">addons<span class="token punctuation">:</span></span>
<span class="line">   chrome<span class="token punctuation">:</span> stable</span>
<span class="line"></span>
<span class="line">install<span class="token punctuation">:</span></span>
<span class="line">   <span class="token operator">-</span> cp <span class="token operator">.</span>env<span class="token operator">.</span>testing <span class="token operator">.</span>env</span>
<span class="line">   <span class="token operator">-</span> travis_retry composer install <span class="token operator">--</span>no<span class="token operator">-</span>interaction <span class="token operator">--</span>prefer<span class="token operator">-</span>dist <span class="token operator">--</span>no<span class="token operator">-</span>suggest</span>
<span class="line"></span>
<span class="line">before_script<span class="token punctuation">:</span></span>
<span class="line">   <span class="token operator">-</span> google<span class="token operator">-</span>chrome<span class="token operator">-</span>stable <span class="token operator">--</span>headless <span class="token operator">--</span>disable<span class="token operator">-</span>gpu <span class="token operator">--</span>remote<span class="token operator">-</span>debugging<span class="token operator">-</span>port<span class="token operator">=</span><span class="token number">9222</span> http<span class="token punctuation">:</span><span class="token comment">//localhost &amp;</span></span>
<span class="line">   <span class="token operator">-</span> php artisan serve <span class="token operator">&amp;</span></span>
<span class="line"></span>
<span class="line">script<span class="token punctuation">:</span></span>
<span class="line">   <span class="token operator">-</span> php artisan dusk</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="circleci" tabindex="-1"><a class="header-anchor" href="#circleci"><span>CircleCI</span></a></h3>
<h4 id="circleci-1-0" tabindex="-1"><a class="header-anchor" href="#circleci-1-0"><span>CircleCI 1.0</span></a></h4>
<p>在 CircleCI 1.0 中运行 Dusk 时需要使用以下配置进行启动。与 TravisCI 相同，我们需要使用 <code v-pre>php artisan serve</code> 命令去启动 PHP 的内置服务器。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">dependencies<span class="token punctuation">:</span></span>
<span class="line">  pre<span class="token punctuation">:</span></span>
<span class="line">    <span class="token operator">-</span> curl <span class="token operator">-</span><span class="token constant">L</span> <span class="token operator">-</span>o google<span class="token operator">-</span>chrome<span class="token operator">.</span>deb https<span class="token punctuation">:</span><span class="token comment">//dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb</span></span>
<span class="line">    <span class="token operator">-</span> sudo dpkg <span class="token operator">-</span>i google<span class="token operator">-</span>chrome<span class="token operator">.</span>deb</span>
<span class="line">    <span class="token operator">-</span> sudo sed <span class="token operator">-</span>i <span class="token string single-quoted-string">'s|HERE/chrome\"|HERE/chrome\" --disable-setuid-sandbox|g'</span> <span class="token operator">/</span>opt<span class="token operator">/</span>google<span class="token operator">/</span>chrome<span class="token operator">/</span>google<span class="token operator">-</span>chrome</span>
<span class="line">    <span class="token operator">-</span> rm google<span class="token operator">-</span>chrome<span class="token operator">.</span>deb</span>
<span class="line"></span>
<span class="line">test<span class="token punctuation">:</span></span>
<span class="line">  pre<span class="token punctuation">:</span></span>
<span class="line">    <span class="token operator">-</span> <span class="token string double-quoted-string">"./vendor/laravel/dusk/bin/chromedriver-linux"</span><span class="token punctuation">:</span></span>
<span class="line">        background<span class="token punctuation">:</span> <span class="token constant boolean">true</span></span>
<span class="line">    <span class="token operator">-</span> cp <span class="token operator">.</span>env<span class="token operator">.</span>testing <span class="token operator">.</span>env</span>
<span class="line">    <span class="token operator">-</span> <span class="token string double-quoted-string">"php artisan serve"</span><span class="token punctuation">:</span></span>
<span class="line">        background<span class="token punctuation">:</span> <span class="token constant boolean">true</span></span>
<span class="line"></span>
<span class="line">  override<span class="token punctuation">:</span></span>
<span class="line">    <span class="token operator">-</span> php artisan dusk</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="circleci-2-0" tabindex="-1"><a class="header-anchor" href="#circleci-2-0"><span>CircleCI 2.0</span></a></h4>
<p>在 CircleCI 2.0 中运行 Dusk 时需要将以下 steps 添加至 build：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">version<span class="token punctuation">:</span> <span class="token number">2</span></span>
<span class="line">jobs<span class="token punctuation">:</span></span>
<span class="line">  build<span class="token punctuation">:</span></span>
<span class="line">    steps<span class="token punctuation">:</span></span>
<span class="line">      <span class="token operator">-</span> run<span class="token punctuation">:</span> sudo apt<span class="token operator">-</span>get install <span class="token operator">-</span>y libsqlite3<span class="token operator">-</span>dev</span>
<span class="line">      <span class="token operator">-</span> run<span class="token punctuation">:</span> cp <span class="token operator">.</span>env<span class="token operator">.</span>testing <span class="token operator">.</span>env</span>
<span class="line">      <span class="token operator">-</span> run<span class="token punctuation">:</span> composer install <span class="token operator">-</span>n <span class="token operator">--</span>ignore<span class="token operator">-</span>platform<span class="token operator">-</span>reqs</span>
<span class="line">      <span class="token operator">-</span> run<span class="token punctuation">:</span> npm install</span>
<span class="line">      <span class="token operator">-</span> run<span class="token punctuation">:</span> npm run production</span>
<span class="line">      <span class="token operator">-</span> run<span class="token punctuation">:</span> vendor<span class="token operator">/</span>bin<span class="token operator">/</span>phpunit</span>
<span class="line"></span>
<span class="line">      <span class="token operator">-</span> run<span class="token punctuation">:</span></span>
<span class="line">        name<span class="token punctuation">:</span> Start Chrome Driver</span>
<span class="line">        command<span class="token punctuation">:</span> <span class="token operator">.</span><span class="token operator">/</span>vendor<span class="token operator">/</span>laravel<span class="token operator">/</span>dusk<span class="token operator">/</span>bin<span class="token operator">/</span>chromedriver<span class="token operator">-</span>linux</span>
<span class="line">        background<span class="token punctuation">:</span> <span class="token constant boolean">true</span></span>
<span class="line"></span>
<span class="line">      <span class="token operator">-</span> run<span class="token punctuation">:</span></span>
<span class="line">        name<span class="token punctuation">:</span> Run Laravel Server</span>
<span class="line">        command<span class="token punctuation">:</span> php artisan serve</span>
<span class="line">        background<span class="token punctuation">:</span> <span class="token constant boolean">true</span></span>
<span class="line"></span>
<span class="line">      <span class="token operator">-</span> run<span class="token punctuation">:</span></span>
<span class="line">        name<span class="token punctuation">:</span> Run Laravel Dusk Tests</span>
<span class="line">        command<span class="token punctuation">:</span> php artisan dusk</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="译者署名" tabindex="-1"><a class="header-anchor" href="#译者署名"><span>译者署名</span></a></h2>
<table>
<thead>
<tr>
<th>用户名</th>
<th>头像</th>
<th>职能</th>
<th>签名</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="https://learnku.com/users/4550" target="_blank" rel="noopener noreferrer">@springjk</a></td>
<td><img src="https://cdn.learnku.com/uploads/avatars/4550_1464580958.png?imageView2/1/w/100/h/100" alt="100"></td>
<td>翻译</td>
<td>再怎么说我也是我西北一匹狼</td>
</tr>
</tbody>
</table>
<hr>
<blockquote>
<p>{note} 欢迎任何形式的转载，但请务必注明出处，尊重他人劳动共创开源社区。</p>
<p>转载请注明：本文档由 Laravel China 社区 <a href="https://laravel-china.org/" target="_blank" rel="noopener noreferrer">laravel-china.org</a> 组织翻译，详见 <a href="https://learnku.com/laravel/t/5756/laravel-55-document-translation-call-come-and-join-the-translation" target="_blank" rel="noopener noreferrer">翻译召集帖</a>。</p>
<p>文档永久地址： <a href="https://learnku.com/docs/laravel" target="_blank" rel="noopener noreferrer">《Laravel 中文文档》</a></p>
</blockquote>
</div></template>


